package codename.carrot.bomberman.network.client;

import android.util.Log;
import codename.carrot.bomberman.network.MessageHandler;
import codename.carrot.bomberman.network.MessageHandler.MessageType;
import codename.carrot.bomberman.network.NetworkConnection.NetworkState;

/**
 * The ClientConnection has the responsibility for setting up the connection as a client through the Client class and also maintaining the connection through ClientConnectionThread.
 * 
 * @see ClientConnectionThread
 * @see Client
 * @author Group A4.
 *
 */
public class ClientConnection {

	/**
	 * String for debugging.
	 */
	private String DEBUG = this.getClass().getSimpleName();
	/**
	 * The connection thread for the client (for sending/receiving from the network).
	 */
	private ClientConnectionThread connectionThread = null;
	/**
	 * Client for setting up the connection (accepting of a socket).
	 */
	private Client client;
	/**
	 * The current state of the connection the class is handling.
	 */
	private NetworkState state = NetworkState.NONE;
	/**
	 * The message handler.
	 */
	private MessageHandler messageHandler;
	
	/**
	 * Constructs a client connection.
	 * @param ipAddress The address to connect to.
	 * @param messageHandler The message handler.
	 */
	public ClientConnection (String ipAddress, MessageHandler messageHandler){
		this.messageHandler = messageHandler;
		terminate();
		Log.d(DEBUG, "Starting as client.");
		this.setState(NetworkState.LISTENING);
		client = new Client(ipAddress, this, this.messageHandler);
		client.start();
	}
	
	/**
	 * Terminates the client both the accepting client and the thread running the connection as well as setting these to null.
	 */
	public void terminate() {
		Log.d(DEBUG, "Terminate network connections.");

		if (client != null) {
			client.terminate();
			client = null;
		}
		if(connectionThread != null){
			connectionThread.terminate();
			connectionThread = null;
		}

		this.setState(NetworkState.NONE);
	}

	/**
	 * Cancel the accepting/connecting of the socket.
	 */
	public void cancelAccept() {
		Log.d(DEBUG, "Canceling connection.");
		this.setState(NetworkState.CONNECTED);
	}
	
	/**
	 * Set the state of the connection.
	 * @param state The new state of the connection.
	 */
	public void setState(NetworkState state) {	    
		if (this.state != state) {
			Log.d(DEBUG, "STATE: " + this.state + " -> " + state);
			messageHandler.obtainMessage(MessageType.STATE, state).sendToTarget();
			this.state = state;
		}
	}

	/**
	 * Set the current connection to be maintained.
	 * @param connectionThread The thread running the network connection.
	 */
	public void setConnection(ClientConnectionThread connectionThread) {
		this.connectionThread = connectionThread;

		if (client != null) {
			Log.d(DEBUG, "Connection set.");
			cancelAccept();
		}
	}

	/**
	 * Send an object over the network to the server.
	 * @param object The object to send.
	 */
	public void send(Object object) {
	    if(connectionThread != null)
	        connectionThread.send(object);
	}

}
